package com.ycy.smartcourseselection.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ycy.smartcourseselection.common.ResCodeEnum;
import com.ycy.smartcourseselection.common.ResData;
import com.ycy.smartcourseselection.dto.login.LoginDTO;
import com.ycy.smartcourseselection.dto.token.UserInfo;
import com.ycy.smartcourseselection.entity.OpenIdManage;
import com.ycy.smartcourseselection.entity.Student;
import com.ycy.smartcourseselection.entity.Teacher;
import com.ycy.smartcourseselection.exception.CustomException;
import com.ycy.smartcourseselection.utils.CommonUtils;
import com.ycy.smartcourseselection.utils.ImageUtils;
import com.ycy.smartcourseselection.utils.TokenUtils;
import com.ycy.smartcourseselection.utils.WeiXinUtils;
import com.ycy.smartcourseselection.vo.login.GetAccessTokenRes;
import com.ycy.smartcourseselection.vo.login.GetQrCodeRes;
import com.ycy.smartcourseselection.vo.login.ScanQrCodeRes;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class LoginService {
    @Resource
    private TeacherService teacherService;
    @Resource
    private StudentService studentService;
    @Lazy
    @Resource
    private OpenIdManageService openIdManageService;

    private GetAccessTokenRes getAccessTokenRes = null;
    private final int tokenExpiresTime = 2; //token到期时长  2小时
    private final ArrayList<ScanQrCodeRes> scanQrCodeResList = new ArrayList<>();

    public ResData<String> login(LoginDTO loginDTO) {
        String accountNumber = loginDTO.getAccountNumber();
        String password = loginDTO.getPassword();
        Integer role = loginDTO.getRole();

        //排除账号或密码为空的情况
        if (StrUtil.isBlank(accountNumber)) {
            if (StrUtil.isBlank(password)) throw new CustomException(ResCodeEnum.BAD_REQUEST, "账号和密码不能为空");
            else throw new CustomException(ResCodeEnum.BAD_REQUEST, "账号不能为空");
        } else {
            if (StrUtil.isBlank(password)) throw new CustomException(ResCodeEnum.BAD_REQUEST, "密码不能为空");
        }

        //0是学生，1是老师
        if(role == 0) return stuLogin(accountNumber,password);
        else return tchLogin(accountNumber,password);
    }

    public ResData<GetQrCodeRes> getQrCode(String qrCodeParams) {
        if(StrUtil.isBlank(qrCodeParams)) throw new CustomException(ResCodeEnum.SERVER_ERROR,"获取二维码参数不能为空");

        //获取accessToken
        String accessToken;
        if(getAccessTokenRes == null || CommonUtils.compareOffsetDate(getAccessTokenRes.getBeginTime(),CommonUtils.getNowTimeStr(),-tokenExpiresTime) < 0) {
            JSONObject accessTokenRes = JSON.parseObject(WeiXinUtils.getAccessToken());
            accessToken = accessTokenRes.get("access_token").toString();
            GetAccessTokenRes tokenRes = new GetAccessTokenRes();
            tokenRes.setAccessToken(accessToken);
            tokenRes.setBeginTime(CommonUtils.getNowTimeStr());
            getAccessTokenRes = tokenRes;
        }else accessToken = getAccessTokenRes.getAccessToken();

        //通过accessToken获取二维码跳转的目标url
        String qrCodeExpireSeconds = "60";
        // String postData = "{\"expire_seconds\": EXPIRE_SECONDS,\"action_name\": \"QR_SCENE\", \"scene_id\": EXTRA_PARAMS}";
        String postData = "{\"expire_seconds\": EXPIRE_SECONDS,\"action_name\": \"QR_LIMIT_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": EXTRA_PARAMS}}}";
        String qrCodeResStr = WeiXinUtils.getQrCodeTicketAndUrl(accessToken, postData.replace("EXPIRE_SECONDS", qrCodeExpireSeconds).replace("EXTRA_PARAMS", qrCodeParams));

        JSONObject qrCodeTicketAndUrlRes = JSON.parseObject(qrCodeResStr);
        String targetUrl = qrCodeTicketAndUrlRes.get("url").toString();  //扫描二维码后跳转的地址

        //通过目标url生成二维码的base64字符串
        Integer width = 300;
        Integer height = 300;
        String qrCode = ImageUtils.createQrCode(targetUrl,width,height, null);
        GetQrCodeRes getQrCodeRes = new GetQrCodeRes();
        getQrCodeRes.setWidth(width);
        getQrCodeRes.setHeight(height);
        getQrCodeRes.setQrCodeBase64(qrCode);
        getQrCodeRes.setExpireSeconds(Integer.parseInt(qrCodeExpireSeconds));
        return ResData.success(getQrCodeRes,"二维码生成成功");
        // return ResData.success(WeiXinUtils.getQrCodeWithValue(),"生成成功");
    }

    //轮询登陆
    public ResData<String> loginByQrCode(String timeStamp) {
        if(StrUtil.isBlank(timeStamp)) throw new CustomException(ResCodeEnum.SERVER_ERROR,"轮询登录时间戳不能为空");

        ScanQrCodeRes currentScanRes = judgeIsScan(timeStamp);
        if(currentScanRes == null) return ResData.success(null,"暂未扫码");
        clearCurrentScanRes(timeStamp);  //当扫码之后，就清空状态数组中的数据

        OpenIdManage openIdManage = openIdManageService.findUserIdByOpenId(currentScanRes.getOpenId());
        if(openIdManage == null) return ResData.success(null,"该微信的用户暂未绑定系统账号");

        LoginDTO loginDTO = openIdManageService.validateTchAndStu(openIdManage.getUserId());
        return login(loginDTO);
    }


    //工具方法 -----------------------------------
    //在WeiXinController中的handleEvent中调用
    public void scanQrCodeResponse(ScanQrCodeRes scanRes) {
        if(StrUtil.isBlank(scanRes.getOpenId())) throw new CustomException(ResCodeEnum.SERVER_ERROR,"扫码结果对象为空");

        scanQrCodeResList.add(scanRes);
        System.out.println("扫描成功! 扫描者："+ scanRes.getOpenId() + ",扫描时间："+ scanRes.getScanTime());
    }

    private ResData<String> stuLogin(String accountNumber,String password) {
        QueryWrapper<Student> stuWrapper = new QueryWrapper<>();
        stuWrapper.eq("student_id", accountNumber);
        List<Student> list = studentService.list(stuWrapper);

        if (list.size() == 0) return ResData.fail(null,"该账号的学生信息不存在");
        if (list.size() > 1) throw new CustomException(ResCodeEnum.SERVER_ERROR, "错误地存在多个该账号的学生信息");
        Student student = list.get(0);
        if (!password.equals(student.getPassword())) return ResData.fail(null,"密码错误");

        UserInfo userInfo = new UserInfo();
        userInfo.setStudent(student);

        return ResData.success(TokenUtils.getToken(userInfo, "STU"),"student");
    }

    private ResData<String> tchLogin(String accountNumber,String password) {
            QueryWrapper<Teacher> teacherQueryWrapper = new QueryWrapper<>();
            teacherQueryWrapper.eq("work_id", accountNumber);
            List<Teacher> teacherList = teacherService.list(teacherQueryWrapper);

            if (teacherList.size() == 0) return ResData.fail(null,"该教师账号不存在");
            if (teacherList.size() > 1) throw new CustomException(ResCodeEnum.SERVER_ERROR, "错误地存在多个该教师账号");

            Teacher teacher = teacherList.get(0);
            if (!password.equals(teacher.getPassword())) return ResData.fail(null,"密码错误");

            UserInfo userInfo = new UserInfo();
            userInfo.setTeacher(teacher);

            if (teacher.getIsAdmin() == 1) return ResData.success(TokenUtils.getToken(userInfo, "TCH"),"admin");
            else return ResData.success(TokenUtils.getToken(userInfo, "TCH"),"teacher");
    }

    public void clearCurrentScanRes(String params) {
        for (int i = 0; i < scanQrCodeResList.size(); i++) {
            if(params.equals(scanQrCodeResList.get(i).getEventKey())) {
                scanQrCodeResList.remove(i);
                break;
            }
        }
    }

    public ScanQrCodeRes judgeIsScan(String params) {
        ScanQrCodeRes currentScanRes = null;
        for (ScanQrCodeRes scanQrCodeRes : scanQrCodeResList) {
            if (params.equals(scanQrCodeRes.getEventKey())) {
                currentScanRes = scanQrCodeRes;
                break;
            }
        }
        return currentScanRes;
    }

}
